iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
自我挑戰組

Viem 介紹系列 第 6

Day 6 - Public Action (1)

  • 分享至 

  • xImage
  •  

Viem 對於 "public" Ethereum RPC 定義了一些動作可以使用
會分為二個章節說明:

Account

先來點基礎的

import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

export const publicClient = createPublicClient({
	chain: mainnet,
	transport: http(),
});
// 取得帳號餘額
const balance = await publicClient.getBalance({
	address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
});
console.log(balance);
// 9065643223449644n

// 取得事務數
const transactionCount = await publicClient.getTransactionCount({
	address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
});

console.log(transactionCount);
// 113

// https://etherscan.io/txs?a=0xA0Cf798816D4b9b9866b5330EEa46a18382f251e&f=2

程式實作:
https://github.com/0xRory/ITHepleViem/blob/main/examples/3_1_pulbicAction_Account.js

Block & Chain

import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

export const publicClient = createPublicClient({
	chain: mainnet,
	transport: http(),
});
// 取得目前 block
const block = await publicClient.getBlock();

// 取得目前區塊交易數
const count = await publicClient.getBlockTransactionCount();

// 監聽 BlockNumber
const unwatchBlockNumber = publicClient.watchBlockNumber({
	onBlockNumber: (blockNumber) => console.log(blockNumber),
});
// 監聽 Block
const unwatchBlock = publicClient.watchBlocks({
	onBlock: (block) => console.log(block),
});

// 取得目前的區塊鏈ID
const chainId = await publicClient.getChainId()

這邊簡單介紹提供的方法,其實 Viem 他整合了監聽還蠻好用的你不用再自己寫。

程式實作:
https://github.com/0xRory/ITHepleViem/blob/main/examples/3_2_publicAction_Block.js

Fee

我個人覺得這個是很重要的 /images/emoticon/emoticon08.gif
下列也是使用代碼來說明:

import { createPublicClient, http, parseEther } from 'viem';
import { mainnet } from 'viem/chains';

export const publicClient = createPublicClient({
	chain: mainnet,
	transport: http(),
});
// 估算每單位燃料價格
// maxPriorityFeePerGas 每單位燃料的優先價格上限
// maxFeePerGas         每單位燃料的價格上限
const { maxFeePerGas, maxPriorityFeePerGas } =
	await publicClient.estimateFeesPerGas();
/**
 * {
 *   maxFeePerGas: 19_788_646_562n,
 *   maxPriorityFeePerGas: 50_000_000n,
 * }
 */

console.log({ maxFeePerGas, maxPriorityFeePerGas });

// gasPrice 估計每單位燃料價錢
const { gasPrice } = await publicClient.estimateFeesPerGas({
	type: 'legacy',
});
/**
 * { gasPrice: 19_788_646_562n }
 */
console.log({ gasPrice });

// 可以參考這篇文章(大前輩)
// https://ithelp.ithome.com.tw/articles/10293790?sc=iThelpR

// export const account = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266';
// // 估計消耗 Gas
// const gasEstimate = await publicClient.estimateGas({
// 	account,
// 	to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
// 	value: parseEther('1'),
// });

// 不過因該會出現錯誤,因為錢包沒錢
// insufficient funds for gas * price + value: address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 have 0 want 1000000000000000000

// 取得歷史費用
const feeHistory = await publicClient.getFeeHistory({
	blockCount: 4,
	rewardPercentiles: [25, 75],
});

console.log(feeHistory);

程式實作:
https://github.com/0xRory/ITHepleViem/blob/main/examples/3_3_publicAction_Fee.js

Filters & Logs

先提前說明一下,這些方法還是要看您連線的 RPC_URL 是否有提供這些功能

這裡分為幾個方法

建立篩選、呈現結果、監控事件、釋放篩選

建立篩選 Filters 大致可分為

呈現結果

如果你是使用

  • createBlockFilter

  • createContractEventFilter

  • createEventFilter

  • createPendingTransactionFilter

    這些方法的話都要用 getFilterChanges 去呈現

import { createPublicClient, http, parseAbiItem } from 'viem';
import { mainnet } from 'viem/chains';

const transport = http('https://ethereum-mainnet-rpc.allthatnode.com');

export const publicClient = createPublicClient({
	chain: mainnet,
	transport: transport,
});

// 監聽新區塊的篩選
const filterBlock = await publicClient.createBlockFilter();

const hashes = await publicClient.getFilterChanges({ filterBlock })
// ["0x10d86dc08ac2f18f00ef0daf7998dcc8673cbcf1f1501eeb2fac1afd2f851128", ...]
// 我測試了很多 public rpc 是沒測試出來

// 監聽事件
const filterEvent = await publicClient.createEventFilter({
	address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // 地址
	event: parseAbiItem(
		'event Transfer(address indexed from, address indexed to, uint256 value)'
	), // 監控的 event
	fromBlock: 16330000n, // 開始篩選
	toBlock: 16330050n,   // 結束篩選
});

const EventLogs = await publicClient.getFilterChanges({ filterEvent })
// [{ ... }, { ... }, { ... }]

const filterPendingTx = await publicClient.createPendingTransactionFilter()
const txHashes = await publicClient.getFilterChanges({ filterPendingTx })
// ["0x89b3aa1c01ca4da5d15eca9fab459d062db5c0c9b76609acb0741901f01f6d19", ...]

const logs = await publicClient.getLogs({
	address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
	event: parseAbiItem(
		'event Transfer(address indexed, address indexed, uint256)'
	),
	args: {
		from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
		to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
	},
	fromBlock: 16330001n,
	toBlock: 16330001n,
});

console.log(logs.length);

getLogs 找尋紀錄,但請記得是你有呼叫合約 event logs 才找得到的喔

幾點注意的:

  • 上面 event 寫法有很多種,個人是比較喜歡這樣的寫法,可參考
  • args 只有在屬性有設定 indexed 才可以使控制喔
  • fromBlocktoBlock 不能和 args 共用 (我自己測試是這樣拉)
  • 能抓出多少 logs 也是看你 RPC 設定而定

程式實作:
https://github.com/0xRory/ITHepleViem/blob/main/examples/3_4_publicAction_Filter.js

今天寫好多啊~自己覺得這幾個都還蠻重要的。/images/emoticon/emoticon33.gif

參考:
https://viem.sh/docs/actions/public/createBlockFilter.html
https://viem.sh/docs/actions/public/createEventFilter.html
https://viem.sh/docs/actions/public/getFilterChanges.html
https://ithelp.ithome.com.tw/articles/10293790?sc=iThelpR
https://viem.sh/docs/actions/public/watchBlocks.html
https://viem.sh/docs/actions/public/getLogs.html


上一篇
Day5 - Introduction to Transports
下一篇
Day 7 - Public Action (2)
系列文
Viem 介紹11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言